import { routerPush } from '@/utils/router/history';
import { iconifyToAntdvIconVNode } from '@ykst/shared';
import { type MenuClickEventHandler, type SubMenuType } from 'ant-design-vue/es/menu/src/interface';
import type { RouteLocationRaw, RouteRecordRaw } from 'vue-router/auto';
import { type VNode } from 'vue';
import { type RouteNamedMap } from 'vue-router/auto/routes';

/** 菜单项点击事件处理函数 */
export const handleMenuClick: MenuClickEventHandler = e => {
  routerPush({ name: e.key } as RouteLocationRaw);
};

/**
 * 自定义菜单类型
 * @desc ant-design ItemType 类型的子集
 */

export interface MenuItem {
  label: string | VNode;
  key: keyof RouteNamedMap;
  level: number;
  title?: string; // 缩进模式下，且label为VNode时，该选项必须
  icon?: VNode;
  children?: MenuItem[];
  __route: RouteRecordRaw; // 当前项的路由
}

/**
 * 路由名称到菜单项显示标签的映射
 * @desc 当需要自定义菜单项显示标签时，可通过该映射来实现
 */
export type LabelKeyMap = Partial<Record<keyof RouteNamedMap, (route: RouteRecordRaw) => VNode>>;

/**
 * 根据路由记录数组获取菜单项列表
 * @param routes 路由记录数组
 * @param labelKeyMap
 */
export const getMenuItemsByRoutes = (
  routes: RouteRecordRaw[],
  level: number = 1,
  labelKeyMap?: LabelKeyMap,
): MenuItem[] => {
  return (
    routes
      // 忽略布局路由，布局路由下必定存在children且children长度为1
      .map(item => (item.meta?.isLayout ? item.children![0] : item))
      // 过滤隐藏路由，以及该隐藏路由的所有子路由
      .filter(item => !item.meta?.hiddenInMenu && item.name)
      // 排序
      .sort((a, b) => (a.meta?.menuOrder ?? 0) - (b.meta?.menuOrder ?? 0))
      // 转换为菜单项列表
      .map(item => {
        // 菜单项的子菜单处理
        let children = item?.children
          ? getMenuItemsByRoutes(item.children, level + 1, labelKeyMap)
          : undefined;
        if (children?.length === 0) {
          children = undefined;
        }

        const routeName = item.name as keyof RouteNamedMap;
        const routeMetaTitle = item.meta?.title!;
        const labelMap = labelKeyMap?.[routeName];

        const label = labelMap ? labelMap(item) : routeMetaTitle;
        const title = labelMap ? routeMetaTitle : undefined;

        return {
          label, // 菜单项显示的标签
          key: routeName, // 菜单项的唯一标识
          title, // 缩进模式下，且label为VNode时，该选项必须
          level, // 菜单项的缩进级别
          icon: item.meta?.icon ? iconifyToAntdvIconVNode(item.meta.icon) : undefined, // 菜单项的图标
          children, // 菜单项的子菜单项列表
          __route: item, // 当前项的路由
        };
      })
  );
};
